package org.snake.nebulae.core.service;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.OptionalDouble;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@Slf4j
public class TaskExecutorReportTask implements Runnable {

    private TaskExecutorManager taskExecutorManager;

    /**
     * 默认平均值
     */
    private double defaultAvgTime = 100;

    public TaskExecutorReportTask(TaskExecutorManager taskExecutorManager) {
        this.taskExecutorManager = taskExecutorManager;
    }

    @Override
    public void run() {
        ConcurrentHashMap<Class<?>, CopyOnWriteArrayList<TaskWrap>> finishedTasks = taskExecutorManager.getFinishedTasks();

        TaskExecutorReport taskExecutorReport = new TaskExecutorReport();

        finishedTasks.forEach((klass, taskWs) -> {
            CopyOnWriteArrayList<TaskWrap> taskWraps = (CopyOnWriteArrayList<TaskWrap>) taskWs.clone();
            taskWs.clear();

            TaskReport taskReport = new TaskReport();

            // 高低位值
            int flag = 0;

            // 任务平均执行时间
            OptionalDouble average = taskWraps
                    .stream()
                    .peek(TaskWrap::recordTime)
                    .mapToLong(TaskWrap::getTaskExecutorTime)
                    .average();

            // 多少任务超过平均时间
            long bigThanAvgCount = taskWraps
                    .stream()
                    .filter(taskWrap -> taskWrap.getTaskExecutorTime() > average.orElse(defaultAvgTime))
                    .count();

            // 标记
            if (!average.isPresent()) {
                log.error("{} 该次任务采用默认执行平均值 {}", klass, defaultAvgTime);
            }

            long halfSize = taskWraps.size() / 2;

            if (bigThanAvgCount > halfSize) {
                flag = 1;
            } else if (bigThanAvgCount < halfSize) {
                flag = -1;
            }

            // 趋势计算
            switch (flag) {
                case 1:
                    taskReport.setTrend("+");
                    break;
                case -1:
                    taskReport.setTrend("-");
                    break;
                default:
                    taskReport.setTrend("=");
            }

            // 其他属性
            taskReport.setExecutorTimeAvg(average.orElse(defaultAvgTime));
            taskReport.setTaskSum(taskWraps.size());

            taskReport.setKlass(klass);
            taskReport.setReportTime(System.currentTimeMillis());
            taskReport.setReportTimeStr(DateUtil.now());

            taskExecutorReport.getReports().add(taskReport);

            // 清空
            boolean done = taskWraps.removeIf(taskWrap -> System.currentTimeMillis() - taskWrap.getTaskExecutorEndTime() > 50);
            if (done) {
                //
            }
        });

        taskExecutorReport.setReportTime(System.currentTimeMillis());
        taskExecutorReport.setReportTimeStr(DateUtil.now());
        taskExecutorReport.setTaskTypeSum(taskExecutorReport.getReports().size());

        OptionalDouble average = taskExecutorReport.getReports().stream().mapToDouble(TaskReport::getExecutorTimeAvg).average();
        taskExecutorReport.setExecutorTimeAvg(average.orElse(0));

        log.info("任务报告: {}", taskExecutorReport);
    }
}
